package com.kefu.chat.service;

import java.util.Arrays;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.google.common.collect.Maps;
import com.kefu.chat.mapper.ChatConversationMapper;
import com.kefu.chat.model.ChatAdmin;
import com.kefu.chat.model.ChatConversation;
import com.kefu.chat.model.ChatConversationMsg;
import com.kefu.chat.vo.ChatConversationDetailVo;
import com.kefu.chat.vo.ChatConversationInsertVo;
import com.kefu.chat.vo.ChatConversationMsgSendResult;
import com.kefu.chat.vo.ChatConversationMsgSendVo;
import com.kefu.chat.vo.ChatConversationSearchVo;
import com.kefu.chat.vo.ChatEventMsg;
import com.kefu.chat.vo.ConversationHistoryMsgQuery;
import com.kefu.chat.vo.ConversationRecallMsgParam;
import com.kefu.chat.vo.GetAllGroupAdminVo;
import com.kefu.chat.vo.GetAllGroupAdminVo.GroupAdmin;
import com.kefu.common.context.KefuContext;
import com.kefu.common.exception.BusinessException;
import com.kefu.common.service.AbstractKefuService;
import com.kefu.sys.mapper.SysUserGroupMapper;
import com.kefu.sys.mapper.SysUserMapper;
import com.kefu.sys.model.SysGroup;
import com.kefu.sys.model.SysUser;
import com.kefu.sys.model.SysUserGroup;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.thread.ThreadUtil;
import icu.mhb.mybatisplus.plugln.core.JoinLambdaWrapper;

/**
 * @author CodeGenerator
 * @date 2022/08/15
 */
@Service
public class ChatConversationService  extends AbstractKefuService<ChatConversation>  {
    @Autowired
    protected ChatConversationMapper chatConversationMapper;
    @Autowired
    SysUserMapper sysUserMapper;
    @Autowired
    ChatCacheService chatCacheService;
    @Autowired
    ChatConversationMsgService chatConversationMsgService;
    @Autowired
    SysUserGroupMapper sysUserGroupMapper;


     
    public List<ChatConversation> conversationList(ChatConversationSearchVo param) {
        LambdaQueryWrapper<ChatConversation> queryWrapper = Wrappers.lambdaQuery(ChatConversation.class)
                .eq(ChatConversation::getTenantId, KefuContext.getTid())
                .lt(ChatConversation::getCreateTime, param.getMaxTime() == 0 ? System.currentTimeMillis() : param.getMaxTime())
                .like(ChatConversation::getUsers, KefuContext.getUid())
                .orderByDesc(ChatConversation::getLastMsgTime).last("limit " + param.getPageSize());
        List<ChatConversation> list = list(queryWrapper);
        Map<String, String> userNameMap = sysUserMapper.getUserNameMap(KefuContext.getTid());
        list.forEach(item -> {
            //单聊，name是另外一个客服的名称
            if (item.getType() == 0) {
                Arrays.asList(item.getUsers().split(",")).forEach(userId -> {
                    if (!userId.equals(KefuContext.getUid())) {
                        item.setName(userNameMap.get(userId));
                        ChatAdmin chatAdmin = chatCacheService.getAdmin(userId);
                        if(chatAdmin!=null){
                            item.setAdminStatus(chatAdmin.getStatus());
                        }
                    }
                });
            }
        });
        return list;
    }

     
    public String conversationAdd(ChatConversationInsertVo param) {
        if(param.getUsers().equals(KefuContext.getUid())){
            throw BusinessException.msg("不能跟自己发起会话");
        }
        //按照id从小到大排序，检索内部会话是否存在，如果存在返回已经存在的
        String users = param.getUsers() + "," + KefuContext.getUid();
        String[] userArray = users.split(",");
        Arrays.sort(userArray);
        users = String.join(",", userArray);
        ChatConversation conversation = getOne(Wrappers.lambdaQuery(ChatConversation.class).eq(ChatConversation::getTenantId, KefuContext.getTid())
                .eq(ChatConversation::getUsers, users));
        if (conversation != null) {
//            update(Wrappers.lambdaUpdate(ChatConversation.class).set(ChatConversation::getLastMsgTime, System.currentTimeMillis())
//                    .set(ChatConversation::getLastMsgContent,null).set(ChatConversation::getLastMsgType,null)
//                    .eq(ChatConversation::getConversationId, conversation.getConversationId()));
            return conversation.getConversationId();
        }
        param.setUsers(users);
        ChatConversation info = param.convert();
        save(info);
        return info.getConversationId();
    }

     
    public ChatConversationDetailVo conversationDetail(String id) {
        ChatConversation conversation = getById(id);
        ChatConversationDetailVo detailVo = BeanUtil.toBean(conversation, ChatConversationDetailVo.class);
        Arrays.asList(conversation.getUsers().split(",")).forEach(userId -> {
            ChatConversationDetailVo.ChatConversationDetailUser detailUser = BeanUtil.toBean(sysUserMapper.selectById(userId),
                    ChatConversationDetailVo.ChatConversationDetailUser.class);
            ChatAdmin chatAdmin = chatCacheService.getAdmin(userId);
            if (chatAdmin != null) {
                detailUser.setAdminStatus(chatAdmin.getStatus());
            }
            detailVo.getUserList().add(detailUser);
        });
        return detailVo;
    }

     
    public ChatConversationMsgSendResult conversationSendMsg(ChatConversationMsgSendVo param) {
        ChatConversationMsg conversationMsg = param.convert();
        ChatEventMsg.AdminGetConversationMsgE msg = BeanUtil.toBean(conversationMsg, ChatEventMsg.AdminGetConversationMsgE.class);
        ChatConversation chatConversation = getById(param.getConversationId());
        String uid = KefuContext.getUid();
        ThreadUtil.execute(()->{
            Arrays.asList(chatConversation.getUsers().split(",")).forEach(userId -> {
                if (!userId.equals(uid)) {
                    ChatAdmin chatAdmin = chatCacheService.getAdmin(userId);
                    if (chatAdmin != null) {
                        chatCacheService.sendEventMsg(chatAdmin.getPollId(), msg);
                    }
                }
            });
        });
        chatConversationMsgService.save(conversationMsg);
        update(Wrappers.lambdaUpdate(ChatConversation.class).set(ChatConversation::getLastMsgContent, conversationMsg.getMsgContent()
                ).set(ChatConversation::getLastMsgTime, conversationMsg.getMsgTime()).set(ChatConversation::getLastMsgType, conversationMsg.getMsgType())
                .eq(ChatConversation::getConversationId, conversationMsg.getConversationId()));
        logger.info("conversationSendMsg:{},{}", param, KefuContext.getKefuContext());
        ChatConversationMsgSendResult result = new ChatConversationMsgSendResult();
        result.setMsgId(conversationMsg.getMsgId());
        result.setMsgTime(conversationMsg.getMsgTime());
        return result;
    }

     
    public List<GetAllGroupAdminVo> getAllGroupAdmin() {
    	JoinLambdaWrapper<SysUserGroup> queryWrapper=joinLambdaQueryWrapper(SysUserGroup.class);
    	
    	queryWrapper.select(SysUserGroup::getGroupId)
	    				.leftJoin(SysGroup.class,  SysGroup::getGroupId,SysUserGroup::getGroupId)
	    				.eq(SysGroup::getGroupType, 0)
	    				.oneToOneSelect(GetAllGroupAdminVo::getGroupName, cb->{
	    					cb.add(SysGroup::getGroupName);
	    				})
    				.end()
	    				.leftJoin(SysUser.class, SysUser::getUserId, SysUserGroup::getUserId)
	    				.eq(SysUser::getTenantId, KefuContext.getTid())
	    				.manyToManySelect(GetAllGroupAdminVo::getUserList, SysUser.class, cb->{
	    					cb.add(SysUser::getUserId,SysUser::getUserName);
	    				})
    				.end();
    	
    	List<GetAllGroupAdminVo>  list=sysUserGroupMapper.joinSelectList(queryWrapper, GetAllGroupAdminVo.class);
    	Map<String,GroupAdmin> userMap=Maps.newHashMap();
    	list.stream().forEach(group->{
    		group.getUserList().stream()
    		.forEach(user->{
    			if(!userMap.containsKey(user.getUserId())) {
    				 ChatAdmin chatAdmin = chatCacheService.getAdmin(user.getUserId());
    				 if(chatAdmin==null){
                         chatAdmin = new ChatAdmin();
                         chatAdmin.setAdminId(user.getUserId());
                         chatAdmin.setAdminName(user.getUserName());
                     }
    				 GetAllGroupAdminVo.GroupAdmin groupAdmin = BeanUtil.toBean(chatAdmin,GetAllGroupAdminVo.GroupAdmin.class);
    				 userMap.put(user.getUserId(), groupAdmin);
    			}
    			group.getAdminList().add(userMap.get(user.getUserId()));
    		});
    		group.getUserList().clear();
    	});
    	
    	return list;
    }

     
    public List<ChatConversationMsg> conversationHistoryMsg(ConversationHistoryMsgQuery param) {
        LambdaQueryWrapper<ChatConversationMsg> wrapper = Wrappers.lambdaQuery(ChatConversationMsg.class);
        wrapper.eq(ChatConversationMsg::getConversationId, param.getConversationId());
        wrapper.lt(ChatConversationMsg::getMsgTime, param.getMaxTime() > 0 ? param.getMaxTime()  : System.currentTimeMillis());
        wrapper.orderByDesc(ChatConversationMsg::getMsgTime);
        wrapper.last("limit "+param.getPageSize());
        List<ChatConversationMsg> list = chatConversationMsgService.list(wrapper);
        String userId = KefuContext.getUid();
        list.forEach(item->{
            if(userId.equals(item.getSender())){
                item.setSenderType(2);
            }
        });
        return list;
    }

     
    public void conversationRecallMsg(ConversationRecallMsgParam param) {
        ChatEventMsg.AdminGetConversationRecallMsg msg = BeanUtil.toBean(param, ChatEventMsg.AdminGetConversationRecallMsg.class);
        ChatConversation chatConversation = getById(param.getConversationId());
        String uid = KefuContext.getUid();
        ThreadUtil.execute(()->{
            Arrays.asList(chatConversation.getUsers().split(",")).forEach(userId -> {
                if (!userId.equals(uid)) {
                    ChatAdmin chatAdmin = chatCacheService.getAdmin(userId);
                    if (chatAdmin != null) {
                        chatCacheService.sendEventMsg(chatAdmin.getPollId(), msg);
                    }
                }
            });
        });
        chatConversationMsgService.update(Wrappers.lambdaUpdate(ChatConversationMsg.class)
                .set(ChatConversationMsg::getRecallFlag,1).eq(ChatConversationMsg::getMsgId, param.getMsgId()));

    }
}
